/*
 * @Date: 2023-04-24 10:24:45
 * @LastEditors: jacky02
 * @LastEditTime: 2023-04-27 20:56:12
 */
import { React, useEffect, useState, useRef } from "react";
import { Menu } from "antd";
import G6React from "@antv/g6";

export default function G6() {
  const [type, setType] = useState("nodeDrag");
  const items = [
    {
      label: "节点图",
      key: "nodeDrag",
    },
    {
      label: "树图",
      key: "tree",
    },
    {
      label: "辐射图",
      key: "radiation",
    },
    {
      label: "弧线图",
      key: "arc",
    },
  ];
  let graph = useRef(null);
  function nodeDrag() {
    fetch("https://gw.alipayobjects.com/os/antvdemo/assets/data/relations.json")
      .then((res) => res.json())
      .then((data) => {
        graph = new G6React.Graph({
          container: "container",
          width: 600,
          height: 600,
          layout: {
            type: "force",
          },
          defaultNode: {
            size: 15,
          },
        });
        graph.data({
          nodes: data.nodes,
          edges: data.edges.map(function (edge, i) {
            edge.id = "edge" + i;
            return Object.assign({}, edge);
          }),
        });
        graph.render();

        graph.on("node:dragstart", function (e) {
          graph.layout();
          refreshDragedNodePosition(e);
        });
        graph.on("node:drag", function (e) {
          const forceLayout = graph.get("layoutController").layoutMethods[0];
          forceLayout.execute();
          refreshDragedNodePosition(e);
        });
        graph.on("node:dragend", function (e) {
          e.item.get("model").fx = null;
          e.item.get("model").fy = null;
        });
      });
  }
  function tree() {
    fetch(
      "https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json"
    )
      .then((res) => res.json())
      .then((data) => {
        graph = new G6React.TreeGraph({
          container: "container",
          width: 600,
          height: 600,
          modes: {
            default: [
              {
                type: "collapse-expand",
                onChange: function onChange(item, collapsed) {
                  const data = item.get("model");
                  data.collapsed = collapsed;
                  return true;
                },
              },
              "drag-canvas",
              "zoom-canvas",
            ],
          },
          defaultNode: {
            size: 26,
            anchorPoints: [
              [0, 0.5],
              [1, 0.5],
            ],
          },
          defaultEdge: {
            type: "cubic-horizontal",
          },
          layout: {
            type: "dendrogram",
            direction: "LR", // H / V / LR / RL / TB / BT
            nodeSep: 30,
            rankSep: 100,
          },
        });
        graph.node(function (node) {
          return {
            label: node.id,
            labelCfg: {
              position:
                node.children && node.children.length > 0 ? "left" : "right",
              offset: 5,
            },
          };
        });

        graph.data(data);
        graph.render();
        graph.fitView();
      });
  }
  function radiation() {
    fetch(
      "https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json"
    )
      .then((res) => res.json())
      .then((data) => {
        graph = new G6React.TreeGraph({
          container: "container",
          width: 600,
          height: 600,
          linkCenter: true,
          modes: {
            default: [
              {
                type: "collapse-expand",
                onChange: function onChange(item, collapsed) {
                  const data = item.get("model");
                  data.collapsed = collapsed;
                  return true;
                },
              },
              "drag-canvas",
              "zoom-canvas",
            ],
          },
          defaultNode: {
            size: 26,
          },
          layout: {
            type: "dendrogram",
            direction: "LR",
            nodeSep: 20,
            rankSep: 100,
            radial: true,
          },
        });

        graph.node(function (node) {
          return {
            label: node.id,
          };
        });

        graph.data(data);
        graph.render();
        graph.fitView();
      });
  }
  function arc() {
    const colors = [
      "rgb(91, 143, 249)",
      "rgb(90, 216, 166)",
      "rgb(93, 112, 146)",
      "rgb(246, 189, 22)",
      "rgb(232, 104, 74)",
      "rgb(109, 200, 236)",
      "rgb(146, 112, 202)",
      "rgb(255, 157, 77)",
      "rgb(38, 154, 153)",
      "rgb(227, 137, 163)",
    ];

    //   const container = document.getElementById('container');
    //   const width = container.scrollWidth;
    //   const height = container.scrollHeight || 500;
    const width = 600;
    const height = 600;
    graph = new G6React.Graph({
      container: "container",
      width,
      height,
      linkCenter: true,
      modes: {
        default: [
          {
            type: "edge-tooltip",
            formatText: function formatText(model) {
              const text =
                "source: " +
                model.sourceName +
                "<br/> target: " +
                model.targetName;
              return text;
            },
          },
        ],
      },
      defaultNode: {
        style: {
          opacity: 0.8,
          lineWidth: 1,
          stroke: "#999",
        },
      },
      defaultEdge: {
        size: 1,
        color: "#e2e2e2",
        style: {
          opacity: 0.6,
          lineAppendWidth: 3,
        },
      },
    });
    graph.on("edge:mouseenter", function (e) {
      const edge = e.item;
      graph.setItemState(edge, "hover", true);
    });
    graph.on("edge:mouseleave", function (e) {
      const edge = e.item;
      graph.setItemState(edge, "hover", false);
    });

    //   if (typeof window !== 'undefined')
    //     window.onresize = () => {
    //       if (!graph || graph.get('destroyed')) return;
    //       if (!container || !container.scrollWidth || !container.scrollHeight) return;
    //       graph.changeSize(container.scrollWidth, container.scrollHeight);
    //     };

    fetch(
      "https://gw.alipayobjects.com/os/basement_prod/70cde3be-22e8-4291-98f1-4d5a5b75b62f.json"
    )
      .then((res) => res.json())
      .then((data) => {
        const origin = [width / 2, height / 2];
        const radius = width < height ? width / 3 : height / 3;
        const edges = data.edges;
        const nodes = data.nodes;
        const nodeMap = new Map();
        const clusterMap = new Map();
        let clusterId = 0;
        const n = nodes.length;
        const angleSep = (Math.PI * 2) / n;
        nodes.forEach(function (node, i) {
          const angle = i * angleSep;
          node.x = radius * Math.cos(angle) + origin[0];
          node.y = radius * Math.sin(angle) + origin[1];
          node.angle = angle;
          nodeMap.set(node.id, node);
          // cluster
          if (node.cluster && clusterMap.get(node.cluster) === undefined) {
            clusterMap.set(node.cluster, clusterId);
            clusterId++;
          }
          const id = clusterMap.get(node.cluster);
          if (node.style) {
            node.style.fill = colors[id % colors.length];
          } else {
            node.style = {
              fill: colors[id % colors.length],
            };
          }
          // label
          node.label = node.name;
          node.labelCfg = {
            position: "center",
            style: {
              rotate: angle,
              rotateCenter: "lefttop",
              textAlign: "start",
            },
          };
        });
        edges.forEach((edge) => {
          edge.type = "quadratic";
          const source = nodeMap.get(edge.source);
          const target = nodeMap.get(edge.target);
          edge.controlPoints = [
            {
              x: origin[0],
              y: origin[1],
            },
          ];
          edge.color = source.style.fill;
          edge.sourceName = source.name;
          edge.targetName = target.name;
        });

        // map the value to node size
        let maxValue = -9999,
          minValue = 9999;
        nodes.forEach(function (n) {
          if (maxValue < n.value) maxValue = n.value;
          if (minValue > n.value) minValue = n.value;
        });
        const sizeRange = [3, 30];
        const sizeDataRange = [minValue, maxValue];
        scaleNodeProp(nodes, "size", "value", sizeDataRange, sizeRange);

        graph.data(data);
        graph.render();
      });

    function scaleNodeProp(nodes, propName, refPropName, dataRange, outRange) {
      const outLength = outRange[1] - outRange[0];
      const dataLength = dataRange[1] - dataRange[0];
      nodes.forEach(function (n) {
        n[propName] =
          ((n[refPropName] - dataRange[0]) * outLength) / dataLength +
          outRange[0];
      });
    }
  }
  function onClick({ key }) {
    setType(key);
  }
  function refreshDragedNodePosition(e) {
    const model = e.item.get("model");
    model.fx = e.x;
    model.fy = e.y;
  }
  useEffect(() => {
    const container = document.getElementById("container");
    // // 声明可视化
    switch (type) {
      case "nodeDrag":
        nodeDrag();
        break;
      case "tree":
        tree();
        break;
      case "radiation":
        radiation();
        break;
      case "arc":
        arc();
        break;
      default:
        nodeDrag();
        break;
    }

    if (typeof window !== "undefined")
      window.onresize = () => {
        if (!graph || graph.get("destroyed")) return;
        if (!container || !container.scrollWidth || !container.scrollHeight)
          return;
        graph.changeSize(container.scrollWidth, container.scrollHeight);
      };
    return () => {
      graph && graph.destroy();
    };
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [type]);
  return (
    <div>
      <div className="menu">
        <Menu
          onClick={onClick}
          defaultSelectedKeys={["nodeDrag"]}
          mode="horizontal"
          items={items}
        />
      </div>
      <div id="container"></div>
    </div>
  );
}
